/*
lo * This file is part of BestApp.

    BestApp is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    BestApp is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with BestApp.  If not, see <http://www.gnu.org/licenses/>.

 */

package org.enate.BESTApp;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
import android.os.Build;
import android.provider.Contacts.People;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Data;
import android.provider.Settings;
import android.telephony.PhoneNumberUtils;
import android.util.Log;
import android.widget.RemoteViews;

public class API {

	//-------------------------------------------------------------------------------------------------------
	private static final String TAG = "API";
	private static final boolean LOLCAT = false;
	
	public static final int pane_VIEW_CONVERSATIONS = 1;
	public static final int pane_VIEW_THREAD = 2;
	

	public static final String pref_SMSMMS = "pref_SMSMMS"; //settings 
	
	
	
	public static final boolean IS_OLD_SDK = Integer.parseInt(Build.VERSION.SDK)<7;	
	public static final Uri CONTACTS_CONTENT_URI_NEW = ContactsContract.Contacts.CONTENT_URI;
	public static final Uri CONTACTS_CONTENT_URI_OLD = People.CONTENT_URI;
	public static final Uri MMS_SMS_CONTENT_URI = Uri.parse("content://mms-sms");
	public static final Uri THREAD_ID_CONTENT_URI = Uri.withAppendedPath(MMS_SMS_CONTENT_URI, "threadID");
	public static final Uri CONVERSATION_CONTENT_URI = Uri.withAppendedPath(MMS_SMS_CONTENT_URI, "conversations");
	public static final Uri SMS_CONTENT_URI = Uri.parse("content://sms");
	public static final Uri SMS_INBOX_CONTENT_URI = Uri.withAppendedPath(SMS_CONTENT_URI, "inbox");
	public static final Uri MMS_CONTENT_URI = Uri.parse("content://mms");
	public static final Uri MMS_INBOX_CONTENT_URI = Uri.withAppendedPath(MMS_CONTENT_URI, "inbox");
	public static final String SMS_ID = "_id";
	public static final String SMS_TO_URI = "smsto:/";
	public static final String SMS_MIME_TYPE = "vnd.android-dir/mms-sms";
	public static final int READ_THREAD = 1;
	public static final int MESSAGE_TYPE_SMS = 1;
	public static final int MESSAGE_TYPE_MMS = 2;
	private static final String TIME_FORMAT_12_HOUR = "MMM dd, yyyy h:mm a";
	private static final String TIME_FORMAT_24_HOUR = "MMM dd, yyyy H:mm";
	
	public static final int WIDGET_TYPE = 0; // Will replace for modular widget types
	

	//-------------------------------------------------------------------------------------------------------
	public static final int INTENT_COMPOSE_SMS = 0;
	public static final int INTENT_VIEWCONVERSATIONS_SMS = 1;

	public static final int INTENT_ACTION_CONTACT_PHOTO_CLICK = 2;
	public static final int INTENT_ACTION_CONTACT_NAME_CLICK = 3;
	public static final int INTENT_ACTION_SMS_MESSAGE_BODY_TEXT_CLICK = 4;
	
	// There's no way to get the click view's ID so:
	public static final String ACTION_CONTACT_PHOTO_CLICK = "Scrolly.API.ACTION_CONTACT_PHOTO_CLICK";
	public static final String ACTION_CONTACT_NAME_CLICK = "Scrolly.API.ACTION_CONTACT_NAME_CLICK";
	public static final String ACTION_SMS_MESSAGE_BODY_TEXT_CLICK = "Scrolly.API.ACTION_SMS_MESSAGE_BODY_TEXT_CLICK";
	

	//-------------------------------------------------------------------------------------------------------
	public static void processWidgetUpdate(Context ctx){
		int[] appWidgetIds = AppWidgetManager.getInstance(ctx).getAppWidgetIds(new ComponentName(ctx, AppWidget4x4.class));
		RemoteViews views = new RemoteViews(ctx.getPackageName(), R.layout.widget_core);
		views.setTextViewText(R.id.sms_unread, API.getUnreadSmsCount(ctx, 0)+"");
		final int N = appWidgetIds.length;
//Why do I need to update twice..
		for (int i = 0; i < N; i++) {AppWidgetManager.getInstance(ctx).updateAppWidget(appWidgetIds[i], views);}
		for (int id:DataProvider.getAllWidgetIds(ctx)){DataProvider.notifyDatabaseModification(id);}
	}
	
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> SMS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>	
	
	//-------------------------------------------------------------------------------------------------------
	
	public static enum DataProviderColumns_CONVERSATIONLIST {_id,date,message_count,recipient_ids,snippet,read,type,error,has_attachment,contact_name,contact_photo,contact_id,lookup_id}	
	public static final String[] PROJECTION_APPWIDGETS_CONVERSATIONLIST = new String[] {"_id","date","message_count","recipient_ids","snippet","read","type","error","has_attachment","contact_name","contact_photo","contact_id","lookup_id"};
    public static final Uri CONTENT_URI_MMS_SMS_CONVERSATIONS = Uri.withAppendedPath(Uri.parse("content://mms-sms/"), "conversations").buildUpon().appendQueryParameter("simple", "true").build();
    public static final String[] projection_SMSConversations= new String[]{"_id", "date", "message_count","recipient_ids","snippet","read","type","error","has_attachment"};
	
    
    private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL("+Phone.NUMBER+",?) AND "+Data.MIMETYPE+"='"+Phone.CONTENT_ITEM_TYPE+"' AND "+Data.RAW_CONTACT_ID+" IN (SELECT raw_contact_id FROM phone_lookup WHERE normalized_number GLOB('+*'))";
    private static final Uri PHONES_WITH_PRESENCE_URI = Data.CONTENT_URI;
    private static final String[] CALLER_ID_PROJECTION = new String[] {Phone.CONTACT_ID,Phone.LOOKUP_KEY,Phone.DISPLAY_NAME,Phone.NUMBER,Phone.LABEL};
    
    //-------------------------------------------------------------------------------------------------------    
    
    
    public static Uri allCanonical = Uri.parse("content://mms-sms/canonical-addresses");
 
    public static Object[] getContactNameorNumber(ContentResolver cr, Object[] ContactLookup, long id) {
    	id = RawIdToContactId(cr, id);
    	ContactLookup[0] = "-9000";
    	ContactLookup[1] = "NAN";
    	ContactLookup[2] = "NAN";
    	Cursor cur;
    	cur = cr.query(allCanonical,null,"_ID="+id,null,null);
		if (null!=cur&&1==cur.getCount()&&cur.moveToFirst()) {
			// Get the phone number by thread's RECIPIENT_ID:
				ContactLookup[1] = cur.getString(1);
				cur.close();
			// Use the number to get the DISPLAY_NAME and CONTACT_ID:
			ContactLookup[1] = PhoneNumberUtils.stripSeparators(ContactLookup[1].toString());
			String selection = CALLER_ID_SELECTION.replace("+",PhoneNumberUtils.toCallerIDMinMatch(ContactLookup[1].toString()));
			cur = cr.query(PHONES_WITH_PRESENCE_URI,CALLER_ID_PROJECTION,selection,new String[] {ContactLookup[1].toString()},null);
			if (null!=cur&&1==cur.getCount()&&cur.moveToFirst()) {
				try {
					ContactLookup[0] = RawIdToContactId(cr,cur.getInt(0));	// CONTACT_ID
					ContactLookup[1] = cur.getString(2)+"";	// DISPLAY_NAME
					ContactLookup[2] = cur.getString(1)+"";	// LOOKUP_KEY
					cur.close();
				}finally {cur.close();}
			}
		}
    	return ContactLookup;
	}
    
	//-------------------------------------------------------------------------------------------------------
	public static byte[] loadContactPhoto(ContentResolver cr, long aId) {
		aId = RawIdToContactId(cr, aId);
        Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, aId);
        InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri);
        if (null==input) {return null;}
        try{
        	byte[] res = new byte[input.available()];
        	input.read(res);
            input.close();
            return res;
        }catch(Exception e) {}
        return null;
	}

	//-------------------------------------------------------------------------------------------------------
    static long RawIdToContactId(ContentResolver resolver, long id) {
    	Cursor crs = resolver.query(ContactsContract.RawContacts.CONTENT_URI, new String[] { ContactsContract.RawContacts._ID, ContactsContract.RawContacts.CONTACT_ID }, ContactsContract.RawContacts._ID + "= ?" , new String[] { String.valueOf(id) }, null);
    	if (null==crs||!crs.moveToFirst()) return id;
    	return crs.getLong(crs.getColumnIndex(ContactsContract.RawContacts.CONTACT_ID));
    }

    //-------------------------------------------------------------------------------------------------------
    public static int getUnreadSmsCount(Context context, long timestamp) {
        String SMS_READ_COLUMN = "read";
        String UNREAD_CONDITION = SMS_READ_COLUMN + "=0";
        if (0<timestamp){UNREAD_CONDITION += " and date<" + String.valueOf(timestamp);}
        int count = 0;
        Cursor cursor = context.getContentResolver().query(SMS_INBOX_CONTENT_URI,new String[] {SMS_ID},UNREAD_CONDITION, null, null);
        if (null!=cursor){
           try {count = cursor.getCount();} 
           finally {cursor.close();}
        }
        if (0<timestamp){count += 1;}
        return count;
    }
	
    //-------------------------------------------------------------------------------------------------------

    public static final int MESSAGE_TYPE_ALL    = 0;
    public static final int MESSAGE_TYPE_INBOX  = 1;
    public static final int MESSAGE_TYPE_SENT   = 2;
    public static final int MESSAGE_TYPE_DRAFT  = 3;
    public static final int MESSAGE_TYPE_OUTBOX = 4;
    public static final int MESSAGE_TYPE_FAILED = 5; // for failed outgoing messages
    public static final int MESSAGE_TYPE_QUEUED = 6; // for messages to send later

    public static boolean isOutgoingFolder(int messageType) {
        return  (messageType==MESSAGE_TYPE_FAILED)||(messageType==MESSAGE_TYPE_OUTBOX)||(messageType==MESSAGE_TYPE_SENT)||(messageType==MESSAGE_TYPE_QUEUED);
    }
    //-------------------------------------------------------------------------------------------------------
    public static String formatTimestamp(ContentResolver cr, long timestamp) {
        String HOURS_24 = "24";
        String hours = Settings.System.getString(cr, Settings.System.TIME_12_24);
        SimpleDateFormat mSDF = new SimpleDateFormat();
        if (HOURS_24.equals(hours)) {mSDF.applyLocalizedPattern(TIME_FORMAT_24_HOUR);} 
        else {mSDF.applyLocalizedPattern(TIME_FORMAT_12_HOUR);}
        return mSDF.format(new Date(timestamp));
    }
    
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> SMS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>	
    //-------------------------------------------------------------------------------------------------------
    // Preference Provider Methods:
	public static CharSequence[] centries;
	public static CharSequence[] centryValues;
	public static Vector<String> ventries;
	public static Vector<String> ventryValues;
	public static List<ResolveInfo> list_availSMSApps;
	static PackageManager pm;
	
	//-------------------------------------------------------------------------------------------------------
    public static boolean bool_availSMSApps(Context ctx){
		pm = ctx.getPackageManager();
    	Intent intent_availSMSApps = new Intent(Intent.ACTION_SEND);
		list_availSMSApps = pm.queryIntentActivities(intent_availSMSApps, 0);
		Collections.sort(list_availSMSApps, new ResolveInfo.DisplayNameComparator(pm));
		ventries = new Vector<String>();
		ventryValues = new Vector<String>();
		for (ResolveInfo ri:list_availSMSApps) {
			try{
				if (ventries.indexOf(ri.loadLabel(pm).toString())<0){ventries.add(ri.loadLabel(pm).toString());}
				try{ventryValues.add(new ComponentName(ri.activityInfo.applicationInfo.packageName,ri.activityInfo.name).flattenToString());}
				catch(Exception e){return false;}
    		}catch(Exception e){return false;}
    	}
		centries = new CharSequence[ventries.size()];
		centryValues = new CharSequence[ventryValues.size()];
		ventries.toArray(centries);
    	ventryValues.toArray(centryValues);
    	ventries = null; ventryValues = null;
    	//for (int i=0;i<ventries.size();i++){Log.d(TAG,"VENTRIES["+i+"] ["+ventries.get(i)+"]");}
		return true;
    }
    
    
	//-------------------------------------------------------------------------------------------------------    
    public static void sendCrashReport(Context ctx, String crashreport) {
    	final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
    	emailIntent.setType("plain/text");
    	emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{""});
    	emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "BESTAPP [Fail Sauce]");
    	emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "BEGIN CRASH REPORT\\n\\n"+crashreport);
    	ctx.startActivity(Intent.createChooser(emailIntent, "Send mail..."));
    }
}
